<?php

namespace app\api\controller;

use app\common\controller\Api;
use app\common\model\LihuaOrder;
use app\common\model\general\LihuaCity;
use app\common\model\LihuaOrderPayment;
use app\common\model\LihuaPaylog;
use app\common\model\LihuaRefund;
use app\common\model\User;
use app\common\model\LihuaWalletOrder;
use app\common\model\OrderRandomFee;
use app\common\model\LihuaOrderActivity;
use my\WxPay;
use my\AliPay;
use my\AliPay2;
use think\Db;
use fast\Http;
use think\Exception;
use think\Log;

/**
 * 支付
 */
class Refund extends Api
{
    protected $_error = '';
    protected $noNeedLogin = [
		'order_refund' , //所有平台退款接口
		'change_refund_status', //服务器异常需要直接修改退款记录状态
		'wait_order_refund', //批量处理过期的待支付订单
	];
    protected $noNeedRight = ['*'];

    public function _initialize()
    {
        parent::_initialize();
	}

	/**
	 * 待支付订单退款钱包金额
	 * 每天下午10点开始统计所有待支付订单
	 * 每次统计100条记录
	 * 统计到后直接去掉订单
	 * */
	public function wait_order_refund(){
		//获取待支付订单
		$whereOrs = [
			'status' => 1,
			'wallet_money_pay|wallet_given_fee' => ['>', 0]
		];
		$list = LihuaOrder::where($whereOrs)->limit(100)->column('sn');
		$refund_list = [];
		foreach ($list as $k => $v) {
			$refund_list[] = $this->cancel_admin($v, '订单超时自动取消');
		}
		$this->success('ok', $list);
	}

	/**后台取消订单操作
     * 
     */
    public function cancel_admin($sn, $applyreason)
    {
        //获取订单详情
        $order = LihuaOrder::getBySn($sn);
        if (!$order) $this->error('非法操作');
        //获取城市代码
        $city_arr = ['',"bj","sh","cz","nj","sz","wx","gz"];
        $city_s = $city_arr[$order['city_id']];
        if($order->status==0){
            $this->error('订单已被取消');
        }
		// //定义退单详情
		// $cancel_obj =[
		// 	'havecancel' => false,//是否已经被取消
		// 	'createrefund' => false,//是否生成了退款记录
		// 	'havesendmessage' => false,//是否推送了信息给送餐系统，通知客服人员进行退单
		// ];
		/*
			* 订单已经成功下单
			* 此时只能通过客服电话进行退单
			* 1、首先要查询订单是否被送餐系统拉取，如果已经进入派送流程，需要对派单系统进行退单处理
			* 2、如果支付方式为在线支付(1=支付宝支付,2=微信支付,3=丽华钱包,6=银联微信,7=云闪付)生成退款记录
			*/
		//第一步先取消订单:此处需要客户和客服沟通后才能点击取消
		$order->cancel_time = date('Y-m-d H:i:s');
		$order->status = 0;
		$cancel_res = $order->save();
		$cancel_obj['havecancel'] = !!$cancel_res;
		//第二步判断是否需要生成退款记录
		// $can_cancel_type = array(1, 2, 3, 6, 7);
		// if (in_array($order->pay_status, $can_cancel_type)){
		//生成退单记录
		// $createRefund = $this->createLihuaRefund($order, 0, $applyreason);
		// $cancel_obj['createrefund'] = !!$createRefund;
		//}
		//这里直接退款，不再做退款记录
		$this->wallet_refund_part($sn);
		// //第三步通知到送餐系统，进行退单处理
		// $api = "http://cz.lihua.com/index.php?s=/WebApi/message/type/20/city/".$city_s."/ordersn/".$order['sn'].".html";
		// $res = Http::get($api);
		// $res_o = json_decode($res, true);
		// $cancel_obj['havesendmessage'] = ($res_o['code']=='ok');
		// Log::record('[cancel_order::sendmessage->'.$res_o['code'], 'info');
		return $sn;
    }

	/**
	 * 所有支付方式退款接口
	 * */
	public function order_refund(){
		$sn = $this->request->request('sn', '');//订单编号 
		$type = (int)$this->request->request('type', '');//支付方式 
		if(!$sn) return $this->error('订单编号异常'); 
		//1=支付宝支付,2=微信支付,3=丽华钱包,6=银联微信,7=云闪付 

		//获取订单详情，如果有钱包部分抵扣的情况下，需要再调用一次钱包退款 
		$arr = $this->getOrderInfoAndPayConf($sn, 2); 
        if ($arr === false) $this->error($this->getError()); 
		list($info, $conf) = $arr; 
		
		//这里需要判断钱包支付金额是否等于订单金额
		if(bcadd($info['wallet_given_fee'], $info['wallet_money_pay'], 2)>0 && $info['pay_type']!=3){
			$this->wallet_refund_part($sn);
		}
		switch ($type)
		{
			case 1:
				$this->alipay_refund($sn); //支付宝退款
				break;
			case 2:
				$this->weixin_refund($sn); //微信退款
				break;
			case 3:
				$this->wallet_refund($sn); //钱包退款
				break;
			case 6:
				$this->union_weixin_refund($sn); //银联微信支付退款
				break;
			case 7:
				$this->union_yun_refund($sn); //云闪付退款
				break;
			default:
				$this->error('支付方式异常');
		}
	}
	
	/**
	 * 支付宝退单1
	 * */
	public function alipay_refund($sn = '')
	{
		//$this->error('请抄送给财务退款');
		//获取订单详情
		$arr = $this->getOrderInfoAndPayConf_refund($sn, 1);
        if ($arr === false) $this->error($this->getError());
		list($info, $configs) = $arr;
        $config  = [
            'gatewayUrl'         => 'https://openapi.alipay.com/gateway.do',
            'appId'              => $configs['appid'],//应用ID
            'signType'           => 'RSA2',
            'notifyUrl'          => 'https://private.lihua.com/api/pay/alicb.html',//回调地址
            'rsaPrivateKey'      => $configs['private_key'],//应用私钥
            'alipayrsaPublicKey' => $configs['public_key'],//支付宝公钥
        ];
        $alipay  = new AliPay2($config);
        $subject = "丽华快餐-{$info['city_name']}-订单{$sn}";
        $data    = $alipay->unifiedOrder_refund($sn, $info['order_amount'], $subject);
        if (!!$data) {
			$updata_order = LihuaOrder::where(['sn'=>$sn])->update(['status'=> 0]);
			$updata_refund = LihuaRefund::where(['order_sn'=>$sn])->update(['status'=> 1]);
			$this->success('OK', $data);
		}else{
			$this->error('退款失败');
		}
	}

	/**
	 * 微信退单2
	 * **/
	public function weixin_refund($sn = '')
	{
		// $this->error('请抄送给财务退款');
        $arr = $this->getOrderInfoAndPayConf_refund($sn, 2);
        if ($arr === false) $this->error($this->getError());
		list($info, $conf) = $arr;
		//如果是没有父级订单，则直接按照原来的方式进行退款
		$notify_url = $this->request->domain() . '/api/refund/weixin_refund_cb.html';
		$config = [
			'appid'      	=> $conf['xcx_id'],//微信开放平台上的应用ID
			'mch_id'     	=> $conf['mch_id'],//商户号
			'api_key'    	=> $conf['api_key'],//微信商户平台上自己设定的api密钥32位
			'notify_url' 	=> $notify_url,//回调地址
			'trade_type' 	=> 'JSAPI',
		];
		$wxpay = new WxPay($config);
		$cityname = '';
		if($info['city_name']=='常州'){ $cityname = 'cz'; };
		if($info['city_name']=='无锡'){ $cityname = 'wx'; };
		if($info['city_name']=='苏州'){ $cityname = 'sz'; };
		if($info['city_name']=='上海'){ $cityname = 'sh'; };
		if($info['city_name']=='南京'){ $cityname = 'nj'; };
		if($info['city_name']=='北京'){ $cityname = 'bj'; };
		if($info['city_name']=='广州'){ $cityname = 'gz'; };
		$body = "lihua-{$cityname}-{$sn}";
		// $this->success('OK', $body);
		$order_amount = $info['order_amount'];
		if($info['wallet_money_pay']>0){
			$order_amount = bcsub($info['order_amount'], $info['wallet_money_pay'], 2);
		}
		$res = $wxpay->weixin_unifiedOrder_refund($sn, $order_amount, $body, $cityname);
		$updata_order = 0;
		if($res['return_code'] == 'SUCCESS'){
			//更新订单状态
			$updata_order = LihuaOrder::where(['sn'=>$sn])->update(['status'=> 0]);
			$updata_refund = LihuaRefund::where(['order_sn'=>$sn])->update(['status'=> 1]);
		}
		$this->success('OK', $res);
	}

	/**
	 * 钱包退款3
	 * **/
	public function wallet_refund($sn = '')
	{
		//这里需要调用钱包系统退款接口进行退款处理
		$data = ['sn'=> $sn];
		try {
			$url    = "http://qianbao.lihua.com/api/wallet/refund_order";
			$ret 	= Http::post($url, $data);
        } catch (\Exception $e) {
			$this->error($e);
        }
		$res 	= json_decode($ret, true);
		if($res['code']==0){
			$this->error($res['msg'], $res['data']);
		}
		$updata_order = LihuaOrder::where([ 'sn'=>$sn ])->update([ 'status'=>0 ]);
		$updata_refund = LihuaRefund::where([ 'order_sn'=>$sn ])->update([ 'status'=>1 ]);
		$this->success($res['msg'], $res['data']);
	}

	/**
	 * 钱包退款_部分退款
	 * **/
	public function wallet_refund_part($sn = '')
	{
		//这里需要调用钱包系统退款接口进行退款处理
		$data = ['sn'=> $sn];
		try {
			$url = "http://qianbao.lihua.com/api/wallet/refund_order";
			$ret = Http::post($url, $data);
        } catch (\Exception $e) {
			$this->error($e);
        }
		$res = json_decode($ret, true);
		return $res;
		// $this->success($res['msg'], $res['data']);
	}

	/**
	 * 改变退款记录的状态
	 * **/
	public function change_refund_status()
	{
		$sn = $this->request->request('sn', '');//订单编号
		$status = (int)$this->request->request('status', '');//状态值
		$updata_refund = LihuaRefund::where([ 'order_sn'=>$sn ])->update([ 'status'=>$status ]);
		$this->success('OK');
	}

	/**
	 * 银联微信退款6 
	 * union_weixin_refund 退款接口
	 * 该支付方式仅微信小程序才有
	 * **/
	public function union_weixin_refund($sn = '')
	{
        $arr = $this->getOrderInfoAndPayConf($sn, 2);
        if ($arr === false) $this->error($this->getError());
		list($info, $conf) = $arr;
		$s = $info['merorder_id'];
		$notify_url = $this->request->domain() . '/api/refund/union_weixin_refund_cb.html'; //回调接口
		$config = [
			'appid'      	=> $conf['xcx_id'],//微信开放平台上的应用ID 
			'mch_id'     	=> $conf['mch_id'],//商户号 
			'api_key'    	=> $conf['api_key'],//微信商户平台上自己设定的api密钥32位 
			'notify_url' 	=> $notify_url,//回调地址 
			'trade_type' 	=> 'JSAPI', 
		];
		$config['mid'] = $conf['mid'];
		$config['tid'] = $conf['tid'];
		$wxpay = new WxPay($config);
		$cityname = '';
		if($info['city_name']=='常州'){ $cityname = 'cz'; };
		if($info['city_name']=='无锡'){ $cityname = 'wx'; };
		if($info['city_name']=='苏州'){ $cityname = 'sz'; };
		if($info['city_name']=='上海'){ $cityname = 'sh'; };
		if($info['city_name']=='南京'){ $cityname = 'nj'; };
		if($info['city_name']=='北京'){ $cityname = 'bj'; };
		if($info['city_name']=='广州'){ $cityname = 'gz'; };
		$body   = "lihua-{$cityname}-{$sn}";
		$s_money = bcsub($info['order_amount'], $info['wallet_money_pay'], 2);
		
		$data   = $wxpay->xcx_unifiedOrder_refund($sn, $s_money, $body, $cityname, $s_money, $info['merorder_id']);
		$params = json_encode($data);
		$url   	= "https://qr.chinaums.com/netpay-route-server/api/";
		$ret 	= Http::post($url, $params);
		$res 	= json_decode($ret, true);

		if($res['errCode'] == 'SUCCESS'){
			$merOrderId = explode("_", $res['merOrderId']);
			$updata_order = LihuaOrder::where([ 'sn'=>$sn ])->update([ 'status'=>0 ]);
			$updata_refund = LihuaRefund::where([ 'order_sn'=>$sn ])->update([ 'status'=>1 ]);
			$this->success('OK', ['data'=>$res, 'updata_order'=>$updata_order, 'updata_refund'=>$updata_refund ]);
		}else{
			$this->error($res);
		}
	}

	/**
	 * 云闪付退款7
	 * **/
	public function union_yun_refund($sn = ''){
		$arr = $this->getOrderInfoAndPayConf($sn, 2);
        if ($arr === false) $this->error($this->getError());
		list($info, $conf) = $arr;
		$notify_url = $this->request->domain() . '/api/refund/union_weixin_refund_cb.html'; //回调接口
		$config = [
			'appid'      	=> $conf['xcx_id'],//微信开放平台上的应用ID 
			'mch_id'     	=> $conf['mch_id'],//商户号 
			'api_key'    	=> $conf['api_key'],//微信商户平台上自己设定的api密钥32位 
			'notify_url' 	=> $notify_url,//回调地址 
			'trade_type' 	=> 'JSAPI', 
		];
		$config['mid'] = $conf['app_mid'];
		$config['tid'] = $conf['app_tid'];
		$wxpay = new WxPay($config);
		$cityname = '';
		if($info['city_name']=='常州'){ $cityname = 'cz'; }; 
		if($info['city_name']=='无锡'){ $cityname = 'wx'; }; 
		if($info['city_name']=='苏州'){ $cityname = 'sz'; }; 
		if($info['city_name']=='上海'){ $cityname = 'sh'; }; 
		if($info['city_name']=='南京'){ $cityname = 'nj'; }; 
		if($info['city_name']=='北京'){ $cityname = 'bj'; }; 
		if($info['city_name']=='广州'){ $cityname = 'gz'; }; 
		$body   = "lihua-{$cityname}-{$sn}";

		$s_money = bcsub($info['order_amount'], $info['wallet_money_pay'], 2);

		$data   = $wxpay->xcx_unifiedOrder_refund($sn, $s_money, $body, $cityname, $s_money, $info['merorder_id']);
		$params = json_encode($data);
		$url   	= "https://qr.chinaums.com/netpay-route-server/api/";
		$ret 	= Http::post($url, $params);
		$res 	= json_decode($ret, true);
		// Log::record('[ union_yun_refund ] '. $sn . "::::" . $res , 'info');
		// Log::record('[ union_yun_refund errCode ] '. $res['errCode'] , 'info');
		// $SSS = ($res['errCode'] == 'SUCCESS');
		// Log::record('[ union_yun_refund errCode success ::: ] '. $SSS , 'info');
		if($res['errCode'] == 'SUCCESS'){
			$merOrderId = explode("_", $res['merOrderId']);
			$updata_order = LihuaOrder::where([ 'sn'=>$sn ])->update([ 'status'=>0 ]);
			$updata_refund = LihuaRefund::where([ 'order_sn'=>$sn ])->update([ 'status'=>1 ]);
			$this->success('OK', ['data'=>$res, 'updata_order'=>$updata_order, 'updata_refund'=>$updata_refund ]);
		}else{
			$this->error($res);
		}
	}

	/**
	 * 
	 * **************
	 * 退款接口回调接口
	 * **************
	 * 
	 * **/

	 /**
	  * 银联支付 退款回调 
	  * union_weixin_refund_cb 退款成功的回调接口
	  **/
	public function union_weixin_refund_cb()
	{
        $xml   = file_get_contents('php://input');
		$wxpay = new WxPay();
		Log::record('[ union_weixin_refund_cb::->xml  ] INIT ' . $xml , 'info');
		return xml(['return_code' => 'SUCCESS', 'return_msg' => 'OK']);

		$res   = $wxpay->xmlstr_to_array($xml);
		
        if ($res['return_code'] == 'SUCCESS') {
            if ($res['result_code'] == 'SUCCESS') {
                $row = $this->getOrderInfo($res['out_trade_no']);
                if ($row) {
                    $money = $row['order_amount'];
                    $checkMoney = (($money * 100) == $res['total_fee']);
					Log::record('[ wxcb::->order_money res_total_fee  ] INIT ' . ($money * 100) . ':::' .$res['total_fee'] . ':::::' . $checkMoney , 'info');
					if ($res['time_end']) {
						$time_end = date_create($res['time_end']);
						$pay_time = date_format($time_end,"Y-m-d H:i:s");
					}
					if ($res['result_code'] == 'SUCCESS') {
						$pay_ok = 1;
						$result_des = '交易支付成功';
					} else {
						$pay_ok = 0;
						$result_des = $res['err_code'].'：'.$res['err_code_des'];
					}
					if (!isset($pay_time)) $pay_time = date('Y-m-d H:i:s');
					$data = [
						'type'           => 6,//微信支付
						'trade_no'       => $res['transaction_id'],
						'out_trade_no'   => $res['out_trade_no'],
						'total_fee'      => $money,
						'order_id'       => $row['id'],
						'user_id'        => $row['user_id'],//$res['attach']
						'pay_ok'         => $pay_ok,
						'pay_time'       => $pay_time,
						'result_code'    => $res['result_code'],
						'result_des'     => $result_des,
						'callbackdata'   => json_encode($res, JSON_UNESCAPED_UNICODE),
					];
					$paylog = LihuaPaylog::create($data);
					if ($res['result_code'] == 'SUCCESS' && $row['status'] == 1) {
						$data = [
							'pay_type'   => 6,
							'pay_status' => 1,
							'pay_time'   => $pay_time,
							'status'     => 2,
						];
						LihuaOrder::update($data, ['id' => $row['id']]);//跟新订单状态
						$this->updateOrderAct($row['sn']);
						LihuaPaylog::update(['upstatus' => 1], ['id' => $paylog->id]);
						LihuaOrderPayment::create([
							'city_id'    => $row['city_id'],
							'order_id'   => $row['id'],
							'order_sn'   => $row['sn'],
							'user_id'    => $row['user_id'],
							'pay_name'   => '微支付',
							'pay_money'  => $money,
							'is_voucher' => 0,
						]);
					}
                }
            }
        }
        return xml(['return_code' => 'SUCCESS', 'return_msg' => 'OK']);
    }

	/****
	 * 
	 * 
	 * 
	 * 
	 * 
	 * ***/


	/**
     * 获取订单信息及支付配置
     * @ApiInternal()
     */
    protected function getOrderInfoAndPayConf_refund($sn = '', $pay_type = 1)
    {
        $info = $this->getOrderInfo_refund($sn);
        if ($info === false) return false;

        $conf = $this->getPayConf($info['city_id'], $pay_type);
        if ($conf === false) return false;
        return [$info, $conf];
	}

	private function getOrderInfo_refund($sn = '')
    {
		$order = LihuaOrder::getBySn($sn);
        if ($order) {
            return $order;
        } else {
            $this->setError('订单不存在');
        }
        return false;
	}


	/**
     * 获取订单信息及支付配置
     * @ApiInternal()
     */
    protected function getOrderInfoAndPayConf($sn = '', $pay_type = 1)
    {
        $info = $this->getOrderInfo($sn);
        if ($info === false) return false;

        $conf = $this->getPayConf($info['city_id'], $pay_type);
        if ($conf === false) return false;
        return [$info, $conf];
	}

	/**
     * 获取支付配置
     * @ApiInternal()
     */
    private function getPayConf($city_id = 0, $pay_type = 1)
    {
        if (in_array($pay_type, [1, 2])) {
            $table = $pay_type == 1 ? 'lihua_alipay' : 'lihua_wxpay';
			$row = Db::name($table)->where(['city_id' => $city_id, 'type' => 1])->field('id,city_id,type,name', true)->find();
			if ($row) return $row;
			$this->setError('未配置支付参数');
        } else $this->setError('请选择支付方式');
        return false;
	}

	/**
	 * 获取订单信息
	 * */
	private function getOrderInfo($sn = '')
    {
		$order = LihuaOrder::getBySn($sn);
        if ($order) {
            return $order;
        } else {
            $this->setError('订单不存在');
        }
        return false;
	}

	/**
     * 获取订单金额等信息
     * @ApiInternal()
     */
    private function updateOrderAct($sn)
    {
        //检查是否享受了某个促销活动
		$orderAct = LihuaOrderActivity::where(['order_sn'=>$sn])->count();
		if($orderAct>0){
			LihuaOrderActivity::where(['order_sn'=>$sn])->update(['paystatus' => 0]);
			Log::record('[ update LihuaOrderActivity ] INIT ' . $sn , 'info');
		}
	}
    
	/**
     * 设置错误信息.
     * @ApiInternal()
     */
    public function setError($error) { $this->_error = $error; }
	
	/**
     * 获取错误信息.
     * @ApiInternal()
     */
    public function getError() { return $this->_error; }
}